package ks.server.controllers.commands.general.user;

import ks.framework.common.Message;
import ks.framework.communicator.Communicator;
import ks.framework.interfaces.IProcessMessage;
import ks.managers.user.User;
import ks.server.controllers.requests.AckRequest;
import ks.server.controllers.requests.NackRequest;
import ks.server.ipc.Listener;
import ks.server.persist.PersistentUserManager;
import ks.server.ServerContext;

import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;

/**
 * Process request to update user account information.
 * 
 * @author Christopher Page
 */
public class AccountController implements IProcessMessage {

	/** Primary agent to whom we can communicate our messages. */
	Communicator com;
	
	public AccountController (Communicator com) {
		this.com = com;
	}
	
	/**
	 * Process the message
	 * 
	 * @param m The message to process.
	 * @return A boolean value.
	 */
	public boolean process(Message m) {

		PersistentUserManager um = ServerContext.getUserManager();
		
		Node userAcc = m.contents();
		
		// Find out its attributes.
		NamedNodeMap nnp = userAcc.getAttributes();
		
		// null on missing attr
		Node playerNode = nnp.getNamedItem("player");
		Node oldPwdNode = nnp.getNamedItem("old-password");
		Node newPwdNode = nnp.getNamedItem("password");
		Node iconNode = nnp.getNamedItem("icon");
		
		String player, oldPwd, newPwd, oldIcon, newIcon;
		
		if (playerNode != null) {
			player = playerNode.getNodeValue();
		}
		else {
			new NackRequest(com).send(m, 4, "Unable to change account details: no player specified.", m.getOriginator());
			return true;
		}
		
		if (!player.equals(m.getOriginator())) {
			new NackRequest(com).send(m, 4, "Unable to change account details: access denied.", m.getOriginator());
			return true;
		}
		
		if (oldPwdNode != null) {
			oldPwd = oldPwdNode.getNodeValue();
		}
		else {
			new NackRequest(com).send(m, 4, "Unable to change account details: password required.", m.getOriginator());
			return true;
		}
		
		User u = um.getUser(player);
		
		if (u != null && u.validate(oldPwd)) {
			oldIcon = u.getIconName();
			if (newPwdNode != null) {
				newPwd = newPwdNode.getNodeValue();
				u.setEncPwd(newPwd);
			}
			if (iconNode != null) {
				newIcon = iconNode.getNodeValue();
				u.setIconName(newIcon);
			}
		}
		else {
			new NackRequest(com).send(m, 4, "Unable to change account details: invalid password.", m.getOriginator());
			return true;
		}
		
		if (!um.updateUser(u.getName())) {
			u.setEncPwd(oldPwd);
			u.setIconName(oldIcon);
			new NackRequest(com).send(m, 3, "Unable to change account details: databse error.", m.getOriginator());
			return true;
		}
		else {
			new AckRequest(com).send(m, "Account details successfully changed.", m.getOriginator());
		}
		
		if (iconNode != null) {
			// produce request updating client on user's new icon
			StringBuilder sb = new StringBuilder("<request version='1.0' id='589a39591271844e3fbe32bbb9281ad9'>");
			sb.append("<account-update player=\"" + player + "\" icon=\"" + iconNode.getNodeValue() + "\" />");
			sb.append("</request>");
			
			Document d = Message.construct(sb.toString());
			Message r = new Message(d);
			r.setRecipient(m.getOriginator());
			r.setBroadcast();
			return com.distribute(r);
		}
		
		return true;
	}
}
